{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 主题三：程序过程与设计"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 目标"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **应用目标**\n",
    "    \n",
    "    - 1. **阶段实战：**\n",
    "        - **股票查询系统的查询结果翻页显示；**\n",
    "        - **信息系统的选择菜单；**\n",
    "    \n",
    "    - 2. **综合实战：**\n",
    "        - **完成股票查询系统的程序结构；**\n",
    "        ![image.png](attachment:image.png)\n",
    "        - **完成信息管理系统的程序结构；**\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **技能目标**\n",
    "    - 1. **能构建模块化的应用程序；**\n",
    "    - 2. **基本技术应用能力**\n",
    "        - 能正确封装设计函数过程，并实现函数定义；\n",
    "        - 能正确调用函数完成数据处理；\n",
    "        - 能在函数中使用装饰器来实现特定应用；\n",
    "        - 能正确lambda表达式简化程序复杂度；\n",
    "        - 能正确使用内置标准函数与函数模块；"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **知识点目标**\n",
    "    - 掌握函数的定义的调用\n",
    "    - 掌握函数的参数\n",
    "    - 掌握函数的返回值\n",
    "    - 掌握函数体与作用域\n",
    "    - 掌握递归函数\n",
    "    - 掌握函数对象\n",
    "    - 掌握函数装饰器\n",
    "    - 掌握lambda表达式\n",
    "    - 掌握顶层函数\n",
    "    - 掌握Python内置标准函数\n",
    "    - 掌握基本标准模块函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的调用\n",
    "&emsp;&emsp;在函数的编程方面，我们最容易用到的是经常调用函数。然后是根据需要封装定义函数，再调用。所以在这类我们先从函数调用运算符开始学习函数调用，然后再学习这些调用的函数是怎么实现的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数的调用语法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 函数调用的语法\n",
    "    - Python提供了函数调用运算符号 ()\n",
    "\n",
    "\n",
    "```python\n",
    "\n",
    "    函数名(参数1，参数2，......)        # 没有返回值\n",
    "    变量 = 数名(参数1，参数2，......)    # 有返回值\n",
    "\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则1：\n",
    "    - 调用函数，参数必须是字面值，已经定义的变量，其他功能语句的返回结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入数据56\n",
      "hello 20 60 56\n"
     ]
    }
   ],
   "source": [
    "a = 20\n",
    "print('hello', a, a+40, input('输入数据'))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则2：\n",
    "    - 如果函数是在其他文件（模块），或者其他目录（包）的文件（模块）中，需要使用import 加载目录下的模块。\n",
    "    - 在使用函数的时候，根据import的方式，需要指定包路径与模块名。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ".DS_Store\n",
      ".ipynb_checkpoints\n",
      "a.txt\n",
      "codes\n",
      "L0_L1_L2_Regularization.ipynb\n",
      "py.png\n",
      "Python入门基础.ipynb\n",
      "Python入门基础@数据与应用.ipynb\n",
      "Python入门基础@数据与应用.pptx\n",
      "Python入门基础@数据运算与流程控制.ipynb\n",
      "Python入门基础@程序过程设计与函数.ipynb\n",
      "Python入门基础@课程说明.ipynb\n",
      "未命名.ipynb\n",
      "未命名1.ipynb\n",
      "课件@第01&02次\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "files = os.listdir()\n",
    "for f in files:\n",
    "    print(f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则3：\n",
    "    - 如下情况，参数是可选的。\n",
    "        - 参数带默认值，比如：sep=','\n",
    "        - 可选的参数，如果没有传递的时候，就使用默认值。\n",
    "    - 除此以外的情况，参数都是必须的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4\n",
      "1。2。3。4\n"
     ]
    }
   ],
   "source": [
    "print(1,2,3,4)\n",
    "print(1,2,3,4,sep='。')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则4：\n",
    "    - 文档中使用....表示的，参数可以多个，不受个数限制"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则5：\n",
    "    - 可以在调用函数的时候，指定参数名；\n",
    "    - 如下情况必须指定参数名：\n",
    "        - 文档中函数参数中出现.....或者\\*的后面的参数，必须指定参数名。\n",
    "    - 如下情况，一定不能指定参数名：\n",
    "        - 文档中函数参数中出现/的前面的参数，不能指定参数名。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello...world\n"
     ]
    }
   ],
   "source": [
    "print('hello', 'world', sep='...')  # 只要sep使用，就必须使用参数名。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则6：\n",
    "    - 参数的顺序必须按照文档中显示的顺序传递。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 规则7：\n",
    "    - 使用参数名的参数，可以不按照顺序使用。  \n",
    "    - 没有使用参数名的参数必须按照顺序使用。\n",
    "    - 一旦某个参数使用了参数名，则后面参数都必须使用参数名。（不使用参数名的参数一定在前面。）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello...word\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<socket.socket fd=60, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print('hello', 'word', flush=True, sep='...')\n",
    "\n",
    "from socket import *\n",
    "socket(AF_INET, SOCK_STREAM, proto=0, fileno=None)\n",
    "socket(type=SOCK_STREAM, family=AF_INET, proto=0, fileno=None)\n",
    "# socket(type=SOCK_STREAM, AF_INET, proto=0, fileno=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 使用help查看函数帮助\n",
    "    - 使用help函数直接查看帮助，从得到的信息中，重点关注如下几个信息：\n",
    "        - 函数的定义（函数名 + 函数参数 + 函数的返回类型）；\n",
    "        - 函数的作用与返回值；\n",
    "        ![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 简单的函数调用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 输入输出函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- input函数\n",
    "\n",
    "```python\n",
    "\n",
    "input(prompt=None, /)\n",
    "    Read a string from standard input.  The trailing newline is stripped.\n",
    "\n",
    "```\n",
    "- **注意：**\n",
    "    - / 前面的参数不允许使用，参数名\n",
    "    ![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入数据：56\n"
     ]
    }
   ],
   "source": [
    "result = input( '请输入数据：')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- print函数\n",
    "\n",
    "```python\n",
    "    print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n",
    "    \n",
    "    Prints the values to a stream, or to sys.stdout by default.\n",
    "    Optional keyword arguments:\n",
    "    file:  a file-like object (stream); defaults to the current sys.stdout.\n",
    "    sep:   string inserted between values, default a space.\n",
    "    end:   string appended after the last value, default a newline.\n",
    "    flush: whether to forcibly fl    \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "fd = open('a.txt', 'w')\n",
    "\n",
    "print('输出值', 20, sep='|', end='。', file=fd, flush=True)\n",
    "\n",
    "fd.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. 数学运算函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- abs函数\n",
    "    - 返回一个数据的绝对值\n",
    "    \n",
    "    \n",
    "```python\n",
    "abs(x, /)\n",
    "    Return the absolute value of the argument.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "a = abs(-1)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- divmod函数\n",
    "    - 求商与余数\n",
    "    \n",
    "\n",
    "```python\n",
    "\n",
    "divmod(x, y, /)\n",
    "    Return the tuple (x//y, x%y).  Invariant: div*y + mod == x.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(4.0, 4.5)\n"
     ]
    }
   ],
   "source": [
    "a = divmod(34.5,  7.5)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- round函数 \n",
    "    - 四舍五入\n",
    "    \n",
    "```python\n",
    "    round(...)\n",
    "        round(number[, ndigits]) -> number\n",
    "    \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "45.785\n"
     ]
    }
   ],
   "source": [
    "a = round(45.7852135, 3)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- min函数\n",
    "    - 求最小值\n",
    "    \n",
    "```python\n",
    "\n",
    "    min(iterable, *[, default=obj, key=func]) -> value\n",
    "    min(arg1, arg2, *args, *[, key=func]) -> value\n",
    "    \n",
    "    With a single iterable argument, return its smallest item. The\n",
    "    default keyword-only argument specifies an object to return if\n",
    "    the provided iterable is empty.\n",
    "\n",
    "```\n",
    "key= func模式是Python独有的编程模式，用函数来决定处理的数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "999\n",
      "赵德柱\n"
     ]
    }
   ],
   "source": [
    "a = min([1, 5, 3, 8, 9, 2], default=999)\n",
    "print(a)\n",
    "b = min([], default=999)\n",
    "print(b)\n",
    "\n",
    "\n",
    "\n",
    "dt = {\n",
    "    '赵德柱': 30, \n",
    "    '黄金花': 80,\n",
    "    '石破天': 70\n",
    "}\n",
    "def  func(p):\n",
    "    return dt[p]\n",
    "\n",
    "c = min(dt, default=999, key=func)\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- max函数\n",
    "    - 求最大值\n",
    "    \n",
    "```python\n",
    "\n",
    "    max(iterable, *[, default=obj, key=func]) -> value\n",
    "    max(arg1, arg2, *args, *[, key=func]) -> value\n",
    "    \n",
    "    With a single iterable argument, return its biggest item. The\n",
    "    default keyword-only argument specifies an object to return if\n",
    "    the provided iterable is empty.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "黄金花 80\n"
     ]
    }
   ],
   "source": [
    "dt = {\n",
    "    '赵德柱': 30, \n",
    "    '黄金花': 80,\n",
    "    '石破天': 70\n",
    "}\n",
    "def  func(p):\n",
    "    return dt[p]\n",
    "\n",
    "c = max(dt, default=999, key=func)\n",
    "print(c, dt[c])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- sum函数\n",
    "    - 求和\n",
    "    \n",
    "```python\n",
    "\n",
    "    sum(iterable, start=0, /)\n",
    "        Return the sum of a 'start' value (default: 0) plus an iterable of numbers\n",
    "\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1028\n"
     ]
    }
   ],
   "source": [
    "a = sum([1, 5, 3, 8, 9, 2], 1000)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- pow函数\n",
    "    - 指数运算\n",
    "    \n",
    "```python\n",
    "\n",
    "    pow(x, y, z=None, /)\n",
    "        Equivalent to x**y (with two arguments) or x**y % z (with three arguments)\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "a = pow(10, 2,)\n",
    "print(a)\n",
    "\n",
    "b = pow(10, 2, 10)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "5. 类型判定函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- id函数\n",
    "    - 返回变量的地址\n",
    "    \n",
    "```python\n",
    "\n",
    "id(obj, /)\n",
    "    Return the identity of an object.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4405122080\n",
      "4405122080\n",
      "4442678512\n",
      "4442678224\n"
     ]
    }
   ],
   "source": [
    "a = 100\n",
    "print(id(a))\n",
    "print(id(100))\n",
    "\n",
    "# 超过一个字节，就会单独创建空间，并拷贝数据\n",
    "b =257\n",
    "print(id(b))\n",
    "print(id(257))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- isinstance函数\n",
    "    - 判定变量的类型\n",
    "    \n",
    "```python\n",
    "\n",
    "    isinstance(obj, class_or_tuple, /)\n",
    "        Return whether an object is an instance of a class or of a subclass thereof.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "a = 'hello'\n",
    "\n",
    "# \n",
    "r = isinstance(a, str)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. 类型转换函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- ord函数\n",
    "    - 返回unicode码\n",
    "    \n",
    "```python\n",
    "    ord(c, /)\n",
    "        Return the Unicode code point for a one-character string.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "27721\n"
     ]
    }
   ],
   "source": [
    "print(ord('汉'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- hex函数\n",
    "    - 返回整数的16进制表示\n",
    "\n",
    "```python\n",
    "    hex(number, /)\n",
    "        Return the hexadecimal representation of an integer.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0x18abef7846071c7\n"
     ]
    }
   ],
   "source": [
    "print(hex(111111111111111111))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- bin函数\n",
    "    - 返回整数的二进制表示\n",
    "    \n",
    "```python\n",
    "    bin(number, /)\n",
    "        Return the binary representation of an integer.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0b1100111011110101111010000000111000111000\n"
     ]
    }
   ],
   "source": [
    "print(bin(888888888888))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- ascii函数\n",
    "    - 返回字符的ASCII码\n",
    "\n",
    "```python\n",
    "    ascii(obj, /)\n",
    "        Return an ASCII-only representation of an object.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'abcdef\\u6c49\\u5b57'\n",
      "1245\n"
     ]
    }
   ],
   "source": [
    "print(ascii('abcdef汉字'))\n",
    "print(ascii(1245))    # 作为字符串处理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- chr函数\n",
    "    - 返回unicode的字符表示\n",
    "    \n",
    "```python\n",
    "    chr(i, /)\n",
    "        Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "汉\n"
     ]
    }
   ],
   "source": [
    "print(chr(0x6c49))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "7. 列表有关函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- len函数\n",
    "    - 返回数据结构的长度\n",
    "    \n",
    "```python\n",
    "    len(obj, /)\n",
    "        Return the number of items in a container.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n"
     ]
    }
   ],
   "source": [
    "print(len([1,2,3,4,5]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- any函数\n",
    "    - 判定序列中元素转换为bool后，是否有True。\n",
    "    \n",
    "```python\n",
    "    any(iterable, /)\n",
    "        Return True if bool(x) is True for any x in the iterable.\n",
    "        \n",
    "        If the iterable is empty, return False.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "a = [1, 2, 3, 4, 5, 0]\n",
    "print(any(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- all函数\n",
    "    - 判定序列中元素转换为bool后，是否都是True。\n",
    "\n",
    "```python\n",
    "    all(iterable, /)\n",
    "        Return True if bool(x) is True for all values x in the iterable.\n",
    "\n",
    "        If the iterable is empty, return True.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "a = [1, 2, 3, 4, 5, 0]\n",
    "print(all(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数变量（函数命名）\n",
    "- 把函数当成一个值使用，赋值给变量，变量也像函数一样使用。\n",
    "- 函数当成值来使用，不能使用`（）`调用运算符号\n",
    "- 函数可以赋值给变量的最大好处是：函数可以命名，与数据值可以命名一样。\n",
    "- 函数变量与原来函数的使用完全一样的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1...2...3\n"
     ]
    }
   ],
   "source": [
    "myfunc = print\n",
    "myfunc(1,2,3,sep='...')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的定义与实现"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 语法\n",
    "\n",
    "```\n",
    "def  函数名(参数名，.....) :\n",
    "    语句\n",
    "    ......\n",
    "    return  值\n",
    "```\n",
    "\n",
    "- 规则：\n",
    "    \n",
    "    - 函数名遵循标识字的命名规则。\n",
    "    - 参数名遵循标识字的命名规则。\n",
    "    - 参数可以多个，使用逗号分隔。\n",
    "    - 没有参数的情况，就直接使用空的括号 def  函数名():\n",
    "    \n",
    "    - 需要输出值，就是用return 值；  \n",
    "    - 不需要输出值，下面三种情况都可以：\n",
    "        - return None\n",
    "        - return\n",
    "        - 省略return语句。\n",
    "    \n",
    "    - 函数必须先定义才能调用。\n",
    "\n",
    "- 规范：\n",
    "    - 函数名的命名规范：建议采用小写字母。\n",
    "    - 函数定义与其他代码之间，前后保留两个空行。 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 简单的函数实现与调用\n",
    "    - 使用函数表示一组代码，通过一个函数名，就可以执行到一组代码，这样代码可以反复调用，提高编码效率。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n",
      "hello\n",
      "hello\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# print_hello()   # 没有定义不能调用\n",
    "\n",
    "def  print_hello():    \n",
    "    print('hello')\n",
    "\n",
    "print_hello()    # 上面已经定义，可以调用。\n",
    "print_hello()    # 上面已经定义，可以调用。\n",
    "print(print_hello())  # 默认返回None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 简单函数参数实现与调用\n",
    "    - 使用参数的好处，就是调用者可以根据需要传递数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n",
      "world\n",
      "ok\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "def  print_hello(info):\n",
    "    print(info)\n",
    "    return\n",
    "\n",
    "\n",
    "print_hello('hello')\n",
    "print_hello('world')\n",
    "print(print_hello('ok'))  # 默认返回None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. 简单返回值实现与调用 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32;40mHello\u001b[0m\n",
      "\u001b[32;40mWorld\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "def  format_color(info):\n",
    "    val = F'\\033[32;40m{info}\\033[0m'\n",
    "    return val\n",
    "\n",
    "print(format_color('Hello'))\n",
    "print(format_color('World'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "5. 函数的文档注释\n",
    "    - 函数体中的第一行，都会作为文档注释使用。\n",
    "\n",
    "\n",
    "\n",
    "-  编码规范：\n",
    "    - 尽管函数文档注释可以是任何字符串，但建议使用三个双引号来作为文档注释。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def  doc_function():\n",
    "    \"\"\"\n",
    "        这是我的文档注释：\n",
    "        该函数是空的。\n",
    "    \"\"\"\n",
    "    pass    # 空语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function doc_function in module __main__:\n",
      "\n",
      "doc_function()\n",
      "    这是我的文档注释：\n",
      "    该函数是空的。\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(doc_function)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在python交互式编程终端查看的帮助：\n",
    ">![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. 函数的参数类型说明\n",
    "    - 可以在函数定义时说明参数类型：\n",
    "\n",
    "\n",
    "```python\n",
    "\n",
    "    def 函数名(参数：类型，....)->返回值类型：\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "def add(a:int, b:int = 55) ->int:\n",
    "    return a+b\n",
    "\n",
    "\n",
    "print(add(45))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "7. 函数的返回值类型说明\n",
    "    - 在Python3以后增加了函数的返回值类型说明，语法如下：\n",
    "\n",
    "```python\n",
    "\n",
    "def 函数名(参数，...) ->类型：\n",
    "    语句\n",
    "    ...\n",
    "    return  值\n",
    "\n",
    "```\n",
    "\n",
    "- 函数的返回类型不是强制的。不过我们申明了什么类型，还是按照类型返回！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20\n"
     ]
    }
   ],
   "source": [
    "def  cal(p, q, r)->int:\n",
    "    \"\"\"\n",
    "    计算和与积，返回整数。\n",
    "    \"\"\"\n",
    "    v= (p+q)*r\n",
    "    return v\n",
    "\n",
    "print(cal(2,3,4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function cal in module __main__:\n",
      "\n",
      "cal(p, q, r) -> int\n",
      "    计算和与积，返回整数。\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(cal)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 下面代码也是没有问题的，但是不规范。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "def  cal2(p, q, r)->int:\n",
    "    \"\"\"\n",
    "    计算和与积，返回整数。\n",
    "    \"\"\"\n",
    "    v= (p+q)*r\n",
    "\n",
    "print(cal2(2,3,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的参数\n",
    "&emsp;&emsp;Python中函数的参数与其他很多语言有差异，使用起来也非常方便。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 参数名（keyword参数）\n",
    "    - Python中函数定义的参数名，在调用的时候，是可以使用的。\n",
    "    - 使用参数名的好处就是不用注意参数的顺序。\n",
    "    - 参数名在调用的时候没使用，语法如下：\n",
    "        - `参数名 = 参数值`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "def add(p1, p2):\n",
    "    return p1 + p2\n",
    "\n",
    "# 使用参数名\n",
    "v = add(p2=55, p1=45)\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 可选参数\n",
    "    - 可选参数也称默认参数，是指在定义函数的时候，参数可以指定默认值，在调用的时候，参数可以不传递，不传递的参数使用默认值作为传递的参数值。\n",
    "    - 默认参数在定义函数的时候指定，语法如下：\n",
    "        - `参数名 = 默认值`\n",
    "    \n",
    "    - 注意：默认参数一定要放在非默认参数后面。换句话说就是，默认参数后面出现非默认参数是语法错误的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "non-default argument follows default argument (<ipython-input-37-ef8d42b4a601>, line 8)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-37-ef8d42b4a601>\"\u001b[0;36m, line \u001b[0;32m8\u001b[0m\n\u001b[0;31m    def add2(p1=45, p2):\u001b[0m\n\u001b[0m            ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m non-default argument follows default argument\n"
     ]
    }
   ],
   "source": [
    "# 定义默认参数\n",
    "def add(p1=45, p2=55):\n",
    "    return p1 + p2\n",
    "\n",
    "v = add()\n",
    "print(v)\n",
    "\n",
    "def add2(p1=45, p2):\n",
    "    return p1 + p2\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 变长参数\n",
    "    - Python提供两种变长参数：带参数名，不带参数名。\n",
    "        - 不带参数名的变长参数：\n",
    "            - 函数定义：`*args`\n",
    "            - 函数会使用：参数值1，....，参数值n\n",
    "            \n",
    "            - 说明：参数使用元组类型传递。\n",
    "            \n",
    "        - 带参数名的变长参数：\n",
    "            - 函数定义：`**kwargs`\n",
    "            - 函数使用：参数名1=参数值1，...., 参数名n=参数值n\n",
    "            \n",
    "            - 说明：参数使用字典传递\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 2, 3, 4, 5)\n"
     ]
    }
   ],
   "source": [
    "def add(*arg):\n",
    "    return arg\n",
    "\n",
    "\n",
    "# v = add(p1=1, p2=2,p3=3,p4=4,p5=5)    # 不带参数名变长参数，不能使用参数名。\n",
    "v = add(1, 2,3,4,5)\n",
    "print(v)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'p1': 1, 'p2': 2, 'p3': 3, 'p4': 4, 'p5': 5}\n"
     ]
    }
   ],
   "source": [
    "def add(**arg):\n",
    "    return arg\n",
    "\n",
    "\n",
    "\n",
    "# v = add(1, 2,3,4,5)    # 带参数名变长参数，不使用参数名会导致错误。\n",
    "v = add(p1=1, p2=2,p3=3,p4=4,p5=5)    \n",
    "print(v)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 变长参数\\*与\\*\\*的顺序\n",
    "    - \\* 与 \\*\\*用来区分带参数名与不带参数名。\n",
    "        - \\* 不带参数名\n",
    "        - \\*\\* 带参数名\n",
    "    - **注意**\n",
    "        - \\*参数只能出现在\\*\\*参数前面\n",
    "        \n",
    "    - 在函数体中，使用\\*与\\*\\*用来表示参数的使用方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-40-6028b7d48620>, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-40-6028b7d48620>\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m    def add(**kwargs, *args):\u001b[0m\n\u001b[0m                      ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "# *变长参数只能用在**前面，否则语法错误。\n",
    "def add(**kwargs, *args):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 变长参数只能一个，不能使用两个"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-41-892fcf8ad5af>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-41-892fcf8ad5af>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m    def add(*args1, *args2):\u001b[0m\n\u001b[0m                    ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "def add(*args1, *args2):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 变长参数中\\*与\\*\\*的作用\n",
    "    - \\*的使用：\n",
    "        - \\*：在函数参数定义中使用，负责把函数调用的参数打包成元组。\n",
    "        - \\*：在函数体中使用，负责把列表解包成参数列表。\n",
    "    - \\*\\*的使用：\n",
    "        - \\*\\*：在函数参数定义中使用，负责把函数调用的参数打包成字典。（定义）\n",
    "        - \\*\\*：在函数体中使用，负责把字典解包成参数列表。 （调用：作为普通参数传递给其他参数调用）  \n",
    "        ![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'tuple'> <class 'dict'>\n",
      "1 2 3 4\n",
      "1 3 4\n"
     ]
    }
   ],
   "source": [
    "def display1(a1,a2,a3,a4):\n",
    "    print(a1,a2,a3,a4)\n",
    "\n",
    "def display2(p1, p2,p3):\n",
    "    print(p1,p2,p3)\n",
    "\n",
    "def add(*args1, **args2):\n",
    "    print(type(args1) , type(args2))\n",
    "    display1(*args1)\n",
    "    display2(**args2)\n",
    "    \n",
    "\n",
    "add(1,2,3,4, p1=1, p2=3, p3=4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 变长参数的解包与压包的进一步应用理解\n",
    "    - 下面通过例子来进一步理解解包。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n"
     ]
    }
   ],
   "source": [
    "# 元组解包，把p元组，解包成参数格式。\n",
    "def add(*args):\n",
    "    sum = 0\n",
    "    for v in args:\n",
    "        sum += v\n",
    "    return sum\n",
    "\n",
    "\n",
    "p = (1,2,3,4)\n",
    "v = add(*p)\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'p1': 1, 'p2': 3, 'p3': 55}\n",
      "{'p1': 30, 'p2': 50, 'p3': 99, 'p4': 88}\n"
     ]
    }
   ],
   "source": [
    "# 元组解包，把p元组，解包成参数格式。\n",
    "def add(**kwargs):\n",
    "    print(kwargs)\n",
    "\n",
    "\n",
    "p= {'p1':1, 'p2':3, 'p3':55}\n",
    "add(**p)  # 解包后，再压包（不能直接使用）\n",
    "# add(p)  # 这是错误的\n",
    "\n",
    "add(p1=30,p2=50,p3=99,p4=88)   # 压包"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 变长参数的使用\n",
    "    - 变长参数就可以按照元组与字典的的使用方式使用。\n",
    "    - 一般带参数名的变长参数，参数名都可以传递，但在函数中使用到的参数才有意义。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "36\n"
     ]
    }
   ],
   "source": [
    "def add(*args):\n",
    "    sum = 0\n",
    "    for v in args:\n",
    "        sum += v\n",
    "    return sum\n",
    "\n",
    "v = add(1, 2, 3, 4)\n",
    "print(v)\n",
    "v = add(1, 2, 3, 4, 5, 6, 7, 8)\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. keyword-only参数\n",
    "    - 也称为强制带命名（关键字参数）：再使用参数的时候，必须使用参数名。\n",
    "    - Python提供了语法机制来约束。\n",
    "    - 语法：  使用特殊参数`*`：\n",
    "        |- 在\\*后的参数，就是强制参数。\n",
    "        |- 在\\*前的参数，参数的使用根据前面讲解的规则。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4\n",
      "1 2 3 4\n",
      "1 30 3 4\n",
      "1 30 3 4\n"
     ]
    }
   ],
   "source": [
    "def add(p1, p2=30, * ,p3, p4):\n",
    "    print(p1,p2,p3,p4)\n",
    "\n",
    "\n",
    "# add(1,2,3,p4=4) 错误，3必须使用参数名（keyword）\n",
    "add(1,2,p3=3,p4=4)\n",
    "add(1,p2=2,p3=3,p4=4)\n",
    "add(1,p3=3,p4=4)\n",
    "add(p1=1,p3=3,p4=4)\n",
    "# add(p1=1,2,p3=3,p4=4)  # 错误，违背了命名参数后面必须是命名参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "5. 参数匹配模型\n",
    "    - 由于Python中函数的参数引入很多参数语法规则，单个语法容易理解，但多个语法放在一起导致我们容易产生混乱，实际上Python函数的参数的语法规则主要还是断字、短句的范畴，只要能唯一确定调用形式即可，这就存在一套匹配规则，了解匹配规则，容易正确使用语法，在语法冲突的时候，容易知道错误在什么地方。\n",
    "    - 匹配规则是：\n",
    "        - 1. 通过位置分配非关键字参数；\n",
    "        - 2. 匹配关键字参数；\n",
    "        - 3. 其他额外的非关键字参数分配到 \\* name 元组中\n",
    "        - 4. 其他额外的关键字参数分配到 \\*\\*name 字典中\n",
    "        - 5. 用默认值分配给在头部未得到分配的参数\n",
    "\n",
    "    - 一个完整的函数参数定义例子\n",
    "        - \\* 与\\*args不能重复使用\n",
    "        - 变长参数不能匹配歧义。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def func(p1, p2, p3=4,p4=5, *,p7, p8,):\n",
    "    print(p1,p2,p3,p4,p5,p6,p7,p8)\n",
    "\n",
    "# def func(p1, p2, p3=4,p4=5, *,p7, p8,*args):    # 匹配歧义\n",
    "#     print(p1,p2,p3,p4,p5,p6\n",
    "    \n",
    "def func2(p1, p2, p3=4,p4=5, *args, p7, p8,):\n",
    "    print(p1,p2,p3,p4,p5,p6,p7,p8,args)\n",
    "    \n",
    "# def func3(p1, p2, p3=4,p4=5, *,p7, p8, **args):    #匹配歧义\n",
    "#     print(p1,p2,p3,p4,p5,p6,p7,p8,args,kwargs)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. 使用参数输出数据\n",
    "    - 这个语法现象，最终是因为Python全部采用对象管理，参数都是传地址，不是传值。\n",
    "    - 整数，复数，小数，"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "[1, 88, 3, 4]\n"
     ]
    }
   ],
   "source": [
    "a = [1,2,3,4]\n",
    "def add (p1,p2):\n",
    "    p1[1] = 88\n",
    "\n",
    "print(a)\n",
    "add(a,40)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "257\n",
      "257\n"
     ]
    }
   ],
   "source": [
    "a = 257\n",
    "def add (p1,p2):\n",
    "    p1 = 400\n",
    "\n",
    "print(a)       # 因为20不可修改，这个对字符串，元组都是一样。\n",
    "add(a,40)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "7. 使用函数作为参数\n",
    "    - 函数参数可以直接使用函数名\n",
    "    - 函数参数也可以使用函数变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[32mhelll!\n",
      "\u001b[32mhelll!\n"
     ]
    }
   ],
   "source": [
    "def mydisplay(val, func):\n",
    "    func(F'\\033[32m{val}!')\n",
    "\n",
    "\n",
    "mydisplay('helll', print)\n",
    "\n",
    "myf = print\n",
    "mydisplay('helll', myf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数的返回值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用return返回数据值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 没有return的默认返回值\n",
    "    - 函数没有return默认返回None。表示没有返回值。也可以使用return返回None。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 返回数据结构（包含将要学习的对象）\n",
    "    - Python函数可以返回任意类型，包含数据结构。不过对元组，列表，字典，集合的返回与使用，提供一些独特的使用方式。 在某些场合下元组的括号可以省略。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(100, 200)\n",
      "[100, 200]\n",
      "{200, 100}\n",
      "{'参数1': 100, '参数2': 200}\n"
     ]
    }
   ],
   "source": [
    "# 返回元组\n",
    "def mymod(p1, p2):\n",
    "    return (p1, p2)\n",
    "\n",
    "print(mymod(100,200))\n",
    "\n",
    "# 返回列表\n",
    "def mymod(p1, p2):\n",
    "    return [p1, p2]\n",
    "\n",
    "print(mymod(100,200))\n",
    "\n",
    "# 返回集合\n",
    "def mymod(p1, p2):\n",
    "    return {p1, p2}\n",
    "\n",
    "print(mymod(100,200))\n",
    "\n",
    "# 返回字典\n",
    "def mymod(p1, p2):\n",
    "    return {'参数1':p1, '参数2':p2}\n",
    "\n",
    "print(mymod(100,200))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 对返回数据结构的处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100 200\n",
      "100 200\n",
      "100 200\n",
      "100 200\n",
      "100 200\n",
      "100 200\n",
      "200 100\n",
      "200 100\n",
      "200 100\n",
      "参数1 参数2\n",
      "参数1 参数2\n",
      "参数1 参数2\n",
      "{'参数1': 100, '参数2': 200}\n"
     ]
    }
   ],
   "source": [
    "# 返回元组\n",
    "def mymod_tuple(p1, p2):\n",
    "    return (p1, p2)\n",
    "\n",
    "\n",
    "# 返回列表\n",
    "def mymod_list(p1, p2):\n",
    "    return [p1, p2]\n",
    "\n",
    "\n",
    "# 返回集合\n",
    "def mymod_set(p1, p2):\n",
    "    return {p1, p2}\n",
    "\n",
    "\n",
    "# 返回字典\n",
    "def mymod_dict(p1, p2):\n",
    "    return {'参数1':p1, '参数2':p2}\n",
    "\n",
    "(r1, r2)= mymod_tuple(100,200)\n",
    "print(r1,r2)\n",
    "[r1, r2]= mymod_tuple(100,200)\n",
    "print(r1,r2)\n",
    "# {r1, r2}= mymod_tuple(100,200)\n",
    "r1, r2= mymod_tuple(100,200)    # 省略\n",
    "print(r1,r2)\n",
    "\n",
    "(r1, r2)= mymod_list(100,200)\n",
    "print(r1,r2)\n",
    "[r1, r2]= mymod_list(100,200)\n",
    "print(r1,r2)\n",
    "# {r1, r2}= mymod_list(100,200)\n",
    "r1, r2= mymod_list(100,200)    # 省略\n",
    "print(r1,r2)\n",
    "\n",
    "(r1, r2)= mymod_set(100,200)\n",
    "print(r1,r2)\n",
    "[r1, r2]= mymod_set(100,200)\n",
    "print(r1,r2)\n",
    "# {r1, r2} = mymod_set(100,200)\n",
    "r1, r2= mymod_set(100,200)    # 省略\n",
    "print(r1,r2)\n",
    "\n",
    "(r1, r2)= mymod_dict(100,200)\n",
    "print(r1,r2)\n",
    "[r1, r2]= mymod_dict(100,200)\n",
    "print(r1,r2)\n",
    "# {r1, r2} = mymod_dict(100,200)\n",
    "r1, r2= mymod_dict(100,200)    # 省略\n",
    "print(r1,r2)\n",
    "\n",
    "r= mymod_dict(100,200)    # 省略\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "参数1 参数2\n"
     ]
    }
   ],
   "source": [
    "r1, _= mymod_dict(100,200)    # 省略\n",
    "print(r1, _)    # 一般会使用_占位。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  返回函数与嵌套函数\n",
    "\n",
    "1. 直接返回一个函数\n",
    "    -  既然函数可以赋值给变量，所以返回函数，使用变量接受返回值，也可以直接使用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello...world\n"
     ]
    }
   ],
   "source": [
    "def  myfunc():\n",
    "    return print;\n",
    "\n",
    "\n",
    "re = myfunc()\n",
    "\n",
    "re('hello','world',sep='...')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 函数嵌套\n",
    "    - 在Python中函数是可以嵌套的。就是在函数中海可以定义函数。\n",
    "    - 函数中嵌套的函数也作为返回值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inner function\n"
     ]
    }
   ],
   "source": [
    "def  outter_func():\n",
    "    def inner_func():\n",
    "        print('inner function')\n",
    "    return inner_func;\n",
    "\n",
    "f = outter_func()\n",
    "f()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### yeild与生成器Generator\n",
    "\n",
    "- python提供了一个yield语句，用来对数据序列的返回操作。\n",
    "\n",
    "\n",
    "1. 语法：\n",
    "    - `yield 数据`\n",
    "    - yield必须在函数中使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "val = yield 2    # SyntaxError: 'yield' outside function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. yield的作用\n",
    "    - 自动返回一个生成器对象\n",
    "    - 这里不解释什么是生成器，但生成器可以创建一个数据序列，可以转换为list类型的数据。\n",
    "    - 但是yield语句不返回数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'generator'> <generator object fc at 0x108d28150>\n",
      "None\n",
      "[100] () set()\n"
     ]
    }
   ],
   "source": [
    "def fc(p):\n",
    "    x = yield p\n",
    "    print(x)    # x位None\n",
    "\n",
    "\n",
    "rv = fc(100)\n",
    "print(type(rv) ,rv)\n",
    "print(list(rv), tuple(rv), set(rv))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[100, 101, 102]\n"
     ]
    }
   ],
   "source": [
    "def fc(p):\n",
    "    yield p\n",
    "    yield p+1\n",
    "    yield p+2\n",
    "\n",
    "\n",
    "rv = fc(100)\n",
    "lt = list(rv)\n",
    "print(lt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-  使用yield产生数据序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4]\n",
      "<class 'generator'>\n"
     ]
    }
   ],
   "source": [
    "def gen_fc():\n",
    "    for i in range(5):\n",
    "        yield i\n",
    "\n",
    "\n",
    "rv = list(gen_fc())\n",
    "print(rv)\n",
    "print(type(gen_fc()))   # 返回一个独特的类型generator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 生成器（generator）函数\n",
    "    - 使用yield语句的函数，就是python中一种特殊的函数：生成器函数。(只要调用依次yield语句，该函数就是生成器函数。)\n",
    "    - 调用生成器函数的时候，并没有执行代码，只是创建了一个生成器（可以理解为代码容器）。\n",
    "    - 只有访问生成器的时候，代码才得到执行。访问生成器使用生成器对象的\\_\\_next\\_\\_函数与send函数。\n",
    "    - 每次调用，执行到yield就暂停，直到下次调用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before\n",
      "0\n",
      "before\n",
      "1\n",
      "before\n",
      "2\n",
      "before\n",
      "3\n",
      "before\n",
      "输出 4\n",
      "4\n"
     ]
    },
    {
     "ename": "StopIteration",
     "evalue": "hello",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-59-1c0094f2f5ac>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     15\u001b[0m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'输出'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrv\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mStopIteration\u001b[0m: hello"
     ]
    }
   ],
   "source": [
    "def gen_fc():\n",
    "    for i in range(5):\n",
    "        print('before')\n",
    "        yield i\n",
    "        print(i)\n",
    "        if i == 4:\n",
    "            return 'hello'    # 抛出StopIteration信号。\n",
    "\n",
    "rv = gen_fc()\n",
    "# 调用生成器容器中代码，并得到yield的值\n",
    "r = rv.__next__()\n",
    "r = rv.__next__()\n",
    "r = rv.__next__()\n",
    "r = rv.__next__()\n",
    "r = rv.__next__()\n",
    "print('输出', r)\n",
    "r = rv.__next__()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Generator类说明\n",
    "    - Generator在typing模块中定义。\n",
    "\n",
    "\n",
    "```python\n",
    "\n",
    "class Generator(collections.abc.Generator, Iterator)\n",
    "     |  Abstract base class for generic types.\n",
    "     |  \n",
    "     |  A generic type is typically declared by inheriting from\n",
    "     |  this class parameterized with one or more type variables.\n",
    "     |  For example, a generic mapping type might be defined as::\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Generator的操作\n",
    "\n",
    "\n",
    "```python\n",
    "\n",
    "        |  __next__(self)\n",
    "        |      Return the next item from the generator.\n",
    "        |      When exhausted, raise StopIteration.\n",
    "        |  \n",
    "        |  close(self)\n",
    "        |      Raise GeneratorExit inside generator.\n",
    "        |  \n",
    "        |  send(self, value)\n",
    "        |      Send a value into the generator.\n",
    "        |      Return next yielded value or raise StopIteration.\n",
    "        |  \n",
    "        |  throw(self, typ, val=None, tb=None)\n",
    "        |      Raise an exception in the generator.\n",
    "        |      Return next yielded value or raise StopIteration.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 生成器操作\n",
    "    - send操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# send从上一次yield结束位置开始\n",
    "def gen_fc():\n",
    "    for i in range(5):\n",
    "        print('before')\n",
    "        yield i\n",
    "        print(i)\n",
    "        if i == 4:\n",
    "            return 'hello'    # 抛出StopIteration信号。\n",
    "\n",
    "rv = gen_fc()\n",
    "# rv.send(0)    # TypeError: can't send non-None value to a just-started generator\n",
    "rv.send(None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 生成器send与\\_\\_next\\_\\_的区别\n",
    "    - send比起\\_\\_next\\_\\_的差异就是可以传递一个值给yield函数，并使得yield语句返回一个值，默认yield函数返回None。\n",
    "    - 因为yield第一次执行暂停，所以send第一次传递的值没有意义，所以send第一次调用只能传递None值。\n",
    "    - 当第二次调用的时候，上一次yield开始执行，并返回这次send传递的值。（或者先执行__next__再执行send一样的效果）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before\n",
      "第01次------\n",
      "888:0\n",
      "before\n",
      "第02次------\n",
      "999:1\n",
      "before\n",
      "第03次------\n",
      "111:2\n",
      "before\n",
      "第04次------\n",
      "222:3\n",
      "before\n",
      "第05次------\n"
     ]
    }
   ],
   "source": [
    "# send与next的区别在于，send在执行的时候，可以传递一个值给yield语句用于返回\n",
    "def gen_fc():\n",
    "    for i in range(5):\n",
    "        print('before')\n",
    "        re = yield i\n",
    "        print(F'{re}:{i}')\n",
    "        if i == 4:\n",
    "            return 'hello'       # 抛出StopIteration信号。\n",
    "\n",
    "rv = gen_fc()\n",
    "rv.send(None)                 # yield后执行不到\n",
    "print('第01次------')\n",
    "rv.send(888)\n",
    "print('第02次------')\n",
    "rv.send(999)\n",
    "print('第03次------')\n",
    "rv.send(111)\n",
    "print('第04次------')\n",
    "rv.send(222)\n",
    "print('第05次------')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. 生成器这种工作方式属于协程的技术范畴\n",
    "    - 所谓协程：就是执行过程中，产生中断（暂停），并返回调用处执行。这个与线程是有区别的，协程系统层面来讲，属于进程或者线程通信的范畴。\n",
    "    - 再系统底层有一个函数就是yield，用来暂时放弃当前分配的CPU执行机会。\n",
    "      ![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成器表达式\n",
    "- 语法：`( 表达式 for 标识字 in 可迭代数据 if 条件 )`\n",
    "- 可以把生成器表达式转换为列表：`[ 表达式 for 标识字 in 可迭代数据 if 条件  ]`\n",
    "- 其中for与if 可以嵌套（每个for可以拥有一个if用来过滤数据，不支持else）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 生成器表达式例子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x108d748e0>"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(x * 2 for x in range(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * 2 for x in range(10)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x108d747d8>"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(print(x) for x in range(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0123456789"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[None, None, None, None, None, None, None, None, None, None]"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[print(x, end='') for x in range(10)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 生成器表达式if使用的例子(不要在if中使用else，没有这个语法，但可以在前面表达式中使用)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 4, 8, 12, 16]"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * 2 for x in range(10) if x%2==0 ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 3, 4, 9, 8, 15, 12, 21, 16, 27]"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * 2 if x%2==0 else x*3 for x in range(10) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 生成器循环嵌套的例子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['1 + 0=1',\n",
       " '2 + 0=2',\n",
       " '2 + 1=3',\n",
       " '3 + 0=3',\n",
       " '3 + 1=4',\n",
       " '3 + 2=5',\n",
       " '4 + 0=4',\n",
       " '4 + 1=5',\n",
       " '4 + 2=6',\n",
       " '4 + 3=7']"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[F'{x} + {y}={x + y}' for x in range(5) for y in range(x)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数体与作用域\n",
    "&emsp;&emsp;函数是独立的块，在Python中，不同的块之间，变量的访问是有约束的。这个部分就来说明函数块与外部的变量的访问规则。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 变量的作用域\n",
    "&emsp;&emsp;因为函数中也可以定义变量，并且参数还传递变量，在函数外部还可以有变量。这些变量名是否可以相同？他们在什么时候释放？（比如函数调用结束后，其中定义的变量释放么？函数测餐食是否释放？）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.  全局变量与局部变量\n",
    "    - 临时变量（也称局部变量）： \n",
    "        - 函数中定义的变量，在函数调用完毕是自动释放的，函数的参数也是自动释放的。这种随着调用环境结束二释放的变量，我们称为临时变量（局部变量）\n",
    "    - 全局变量\n",
    "        - 程序结束才释放的变量，我们称为全局变量。（Python中存在顶层函数，其中定义的变量都是全局变量）\n",
    "        \n",
    "    - 全局变量与局部变量使用规则：\n",
    "        - 在函数中，可以使用全局变量\n",
    "        - 在全局中，不能使用局部变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "函数局部： 40\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "name 'la' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-72-431be1db1f02>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0mgb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m40\u001b[0m    \u001b[0;31m# 全局变量\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'全局：'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mla\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'la' is not defined"
     ]
    }
   ],
   "source": [
    "def  func():\n",
    "    la = 30     # 局部变量\n",
    "    print('函数局部：',gb)\n",
    "gb = 40    # 全局变量\n",
    "func()\n",
    "print('全局：',la)     # la不能被使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 全局变量与局部变量的命名冲突\n",
    "    - 全局变量与局部变量在不同的运行环境中，可以有相同的变量名；\n",
    "        - 规则：变量名相同，使用的时候遵循一个规则：局部优先。\n",
    "        - 规则：没有冲突，变量不会产生访问歧义，直接使用全局变量，但全局中不能使用局部变量；\n",
    "    - 为了区分变量是全局还是局部变量，python引入了一个关键字来处理。\n",
    "        - global\n",
    "    - 全局变量申明的语法：`global  变量名1, 变量名2,......`\n",
    "        - 就算没有在全局定义全局变量，在函数内部使用global声明的变量都是全局变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "函数局部： 30 888 999 777\n",
      "全局： 40 888 999 777\n"
     ]
    }
   ],
   "source": [
    "def  func():\n",
    "    global glb,glc, gld\n",
    "    gla = 30     # 局部变量\n",
    "    \n",
    "    glb = 888    # 全局变量\n",
    "    glc = 999    # 全局变量\n",
    "    gld = 777\n",
    "    \n",
    "    \n",
    "    print('函数局部：',gla, glb, glc,gld)    # 局部优先\n",
    "    \n",
    "gla = 40    # 全局变量\n",
    "glb = 50    # 全局变量\n",
    "glc = 50    # 全局变量\n",
    "func()\n",
    "print('全局：',gla, glb, glc,gld)     # la不能被使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 函数嵌套中的变量作用域\n",
    "    - 函数可以嵌套，导致变量的作用域更加复杂。但遵循一个总得规则：\n",
    "        - 内层可以访问外层，外层不能访问内层。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "name 'a2' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-83-139c6e02a295>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     13\u001b[0m \u001b[0ma0\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0mfunc_1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-83-139c6e02a295>\u001b[0m in \u001b[0;36mfunc_1\u001b[0;34m()\u001b[0m\n\u001b[1;32m     10\u001b[0m         \u001b[0mfunc_3\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mfunc_2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m \u001b[0ma0\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'a2' is not defined"
     ]
    }
   ],
   "source": [
    "\n",
    "def func_1():\n",
    "    a1 = 1\n",
    "    \n",
    "    def func_2():\n",
    "        a2 = 2\n",
    "        def func_3():\n",
    "            a3 = 3\n",
    "            print(a0, a1, a2, a3)\n",
    "        func_3()\n",
    "    func_2()\n",
    "    # print(a2)    # 外层不能访问内层：NameError: name 'a2' is not defined\n",
    "a0 = 0\n",
    "\n",
    "func_1()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. 内外层的变量名冲突\n",
    "    - 可以使用nonlocal来解决内外层的变量名冲突与作用域问题\n",
    "    - 语法： `nonlocal  外层变量, 外层变量, ......`\n",
    "    - 规则：\n",
    "        - nonlocal与global的使用差别是：nonlocal 绑定的变量必须在外层申明过，global的不需要申明。 \n",
    "        - nonlocal不能绑定全局变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 22 33\n",
      "22\n"
     ]
    }
   ],
   "source": [
    "\n",
    "def func_1():\n",
    "    a1 = 11\n",
    "    \n",
    "    def func_2():\n",
    "        nonlocal a1\n",
    "        # nonlocal a0     # SyntaxError: no binding for nonlocal 'a0' found\n",
    "        a1 = 22\n",
    "        def func_3():\n",
    "            a3 = 33\n",
    "            print(a0, a1, a3)\n",
    "        func_3()\n",
    "    func_2()\n",
    "    print(a1)    # 外层不能访问内层：NameError: name 'a2' is not defined\n",
    "a0 = 0\n",
    "\n",
    "func_1()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 闭包\n",
    "\n",
    "- 闭包这个概念也与作用域有关，上面变量作用域都是函数调用完毕变量就被释放，但这种情况存在一种问题。\n",
    "    - 当函数返回函数，就存在调用函数结束，返回的嵌套函数还在运行，这个函数的外层环境已经被释放，如果其中引用的外层变量就不存在，这种情况的解决，在Python中引入了闭包的概念来解决。\n",
    "    \n",
    "- 闭包\n",
    "    - 闭包 = 内部嵌套函数 + 外部引用环境\n",
    "        - 闭包：内部嵌套函数 + 外部引用环境打包成为一个新的整体，可以解决了函数编程中的嵌套所引发的问题；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "41\n"
     ]
    }
   ],
   "source": [
    "def out_func():\n",
    "    a = 40\n",
    "    \n",
    "    \n",
    "    def in_func():\n",
    "        nonlocal a   # 不使用这个语句，a赋值当成当前局部变量处理。\n",
    "        a = a + 1\n",
    "        print(a)\n",
    "    \n",
    "    \n",
    "    \n",
    "    return in_func\n",
    "\n",
    "\n",
    "in_f = out_func()   # 这儿调用完毕，a应该释放，但因为存在函数返回，会把in_func函数与out_func引用环境一起打包（这是内存管理的范畴）。\n",
    "\n",
    "in_f()   # 该函数引用的外层环境，因为闭包而存在。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数递归\n",
    "- 在Python中支持函数调用函数本身的语法（实际基本上所有语言都支持），这种语法现象就是递归。\n",
    "- 有的时候使用好递归，可以很方便的解决某些问题。\n",
    "- 函数调用函数，逻辑上是无穷递归调用的，所以使用递归的时候处理好两个问题：\n",
    "    - 递归结束\n",
    "    - 递归的返回值（这个可以用来产生二叉树）\n",
    "\n",
    "- 函数调用函数本身的语法规则与函数调用是一样的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 递归的使用技巧\n",
    "    - 使用条件结束递归调用。\n",
    "    - 选择递归的思路：使用初中的数列通项式$f_n(x) =f_{n-1}(x) + a_0 $。\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 使用递归显示某个目录"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "\n",
    "def list_dir(d, depth):\n",
    "    fd = os.path.basename(d)\n",
    "    # print('  ' * depth, fd, sep='|-')\n",
    "    if os.path.isdir(d):\n",
    "        files = os.listdir(d)\n",
    "        for file in files:\n",
    "            file_path = os.path.join(d, file)\n",
    "            list_dir(file_path, depth + 1)\n",
    "\n",
    "\n",
    "list_dir('.', 1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 使用递归生成目录树"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "\n",
    "def list_dir(d, depth):\n",
    "    fd = os.path.basename(d)\n",
    "    # print('\\t' * depth, fd, sep='|-')\n",
    "    v = []\n",
    "    if os.path.isdir(d):\n",
    "        files = os.listdir(d)\n",
    "        for file in files:\n",
    "            file_path = os.path.join(d, file)\n",
    "            r = list_dir(file_path, depth + 1)\n",
    "            v.append(r)\n",
    "    return {d: v}\n",
    "\n",
    "\n",
    "re = list_dir('.', 1)\n",
    "# print(re)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数对象\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数对象的类型\n",
    "\n",
    "1. 我们在前面看见，函数可以作为函数值赋值给变量，这个函数实际是作为函数对象而存在。既然函数可以作为对象值赋值给i变量，函数变量就与函数一样，具备如下变量与函数共有的操作：\n",
    "    - 函数变量像函数一样调用；\n",
    "    - 函数变量，可以作为变量使用，在函数参数与返回值中使用；\n",
    "    - 函数可以使用在变量使用的任何场景；\n",
    "2. 作为函数对象，函数可以想对象一样操作，对象具备如下操作：\n",
    "    - 类型：type\n",
    "    - 地址：id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<function my_func at 0x10d692c80>\n",
      "4519963776\n",
      "<class 'function'>\n"
     ]
    }
   ],
   "source": [
    "def my_func(a, b)->int:\n",
    "    return a + b\n",
    "\n",
    "print(my_func)   # 作为变量值使用\n",
    "print(id(my_func))   # 地址\n",
    "print(type(my_func))  # 类型 \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. builtins.function的帮助\n",
    "    - 因为fuction动态构建，使用help（builtins.function）无法查看帮助。只有动态返回的类型才能查看。\n",
    "        - help(type(my_func))  能使用这种方式查看到帮助，\n",
    "    - builtins.function的源代码截图如下：\n",
    "    ![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'function' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-1e26c449b31c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 使用代码获取帮助\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mhelp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m\u001b[0mfunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'function' is not defined"
     ]
    }
   ],
   "source": [
    "# 使用代码获取帮助\n",
    "help(function)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'function' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-14-5c9b353bc32c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 不能直接使用function类，函数对象是根据代码而创建的对象，类型时function类型，这个类型在builtins模块中定义。\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m\u001b[0mfunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'function' is not defined"
     ]
    }
   ],
   "source": [
    "# 不能直接使用function类，函数对象是根据代码而创建的对象，类型时function类型，这个类型在builtins模块中定义。\n",
    "a =function()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'function'>\n",
      "Help on class function in module builtins:\n",
      "\n",
      "class function(object)\n",
      " |  function(code, globals[, name[, argdefs[, closure]]])\n",
      " |  \n",
      " |  Create a function object from a code object and a dictionary.\n",
      " |  The optional name string overrides the name from the code object.\n",
      " |  The optional argdefs tuple specifies the default argument values.\n",
      " |  The optional closure tuple supplies the bindings for free variables.\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __call__(self, /, *args, **kwargs)\n",
      " |      Call self as a function.\n",
      " |  \n",
      " |  __get__(self, instance, owner, /)\n",
      " |      Return an attribute of instance, which is of type owner.\n",
      " |  \n",
      " |  __new__(*args, **kwargs) from builtins.type\n",
      " |      Create and return a new object.  See help(type) for accurate signature.\n",
      " |  \n",
      " |  __repr__(self, /)\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  __annotations__\n",
      " |  \n",
      " |  __closure__\n",
      " |  \n",
      " |  __code__\n",
      " |  \n",
      " |  __defaults__\n",
      " |  \n",
      " |  __dict__\n",
      " |  \n",
      " |  __globals__\n",
      " |  \n",
      " |  __kwdefaults__\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 通过定义的函数才能获取这个类型与对象\n",
    "def my_func(a, b)->int:\n",
    "    return a + b\n",
    "\n",
    "print(type(my_func))\n",
    "\n",
    "# 获取类型的帮助\n",
    "help(type(my_func))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用函数对象"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 函数的属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n",
      "{'a': <class 'int'>, 'b': <class 'int'>, 'c': <class 'int'>, 'd': <class 'int'>, 'return': <class 'int'>}\n",
      "<code object my_func at 0x10d732810, file \"<ipython-input-30-5172c4dc30fd>\", line 4>\n",
      "(3,)\n",
      "{}\n",
      "{'c': 40}\n",
      "------\n",
      "my_func\n",
      "\n",
      "    注释文档\n",
      "    \n",
      "__main__\n",
      "112\n",
      "<function my_func at 0x10d671730>\n",
      "<class 'function'>\n",
      "['__repr__', '__call__', '__get__', '__new__', '__closure__', '__doc__', '__globals__', '__module__', '__code__', '__defaults__', '__kwdefaults__', '__annotations__', '__dict__', '__name__', '__qualname__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']\n",
      ": 3\n"
     ]
    }
   ],
   "source": [
    "import builtins\n",
    "\n",
    "\n",
    "def my_func(a: int, b: int=3, *, c: int = 40, d: int) -> int:\n",
    "    \"\"\"\n",
    "    注释文档\n",
    "    \"\"\"\n",
    "    re = 30\n",
    "    return a + b\n",
    "\n",
    "\n",
    "# 使用函数对象\n",
    "print(my_func.__closure__)       # 闭包\n",
    "print(my_func.__annotations__)   # 参数与返回值说明\n",
    "print(my_func.__code__)     # 代码\n",
    "print(my_func.__defaults__)    # 缺省值\n",
    "print(my_func.__dict__)      # 字典(用来存放属性列表，函数没有)\n",
    "# print(my_func.__globals__)     # 全局\n",
    "print(my_func.__kwdefaults__)   # keyword缺省\n",
    "print('------')\n",
    "print(my_func.__name__)    # 函数名\n",
    "print(my_func.__doc__)       # 函数的注释文档\n",
    "print(my_func.__module__)    # 函数所在模块\n",
    "print(my_func.__sizeof__())    # 函数占用的内存大小\n",
    "print(my_func.__str__())        # 代表函数的字符串\n",
    "print(my_func.__class__)     # 函数的类型\n",
    "print(my_func.__dir__())     # 函数的目录（成员）\n",
    "r = my_func.__call__(1, 2, c=3, d=4)    # 使用__call__调用函数。\n",
    "print(':', r)   # 调用方的返回值\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数对象中的闭包属性\n",
    "\n",
    "\n",
    "1. 函数闭包产生的条件：\n",
    "    - 内部函数\n",
    "    - 作为返回值返回到外部\n",
    "    - 在外部调用。\n",
    "    \n",
    "    \n",
    "    - 只有内部函数使用了外部的变量，才会生成闭包\n",
    "    \n",
    "    - 闭包是一个元组（因为嵌套的层数，可能是多个）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "函数的闭包： (<cell at 0x10d625d68: int object at 0x10b2b3d40>,)\n",
      "45\n",
      "函数的闭包： (<cell at 0x10d625d68: int object at 0x10b2b3d40>,)\n",
      "<class 'tuple'>\n",
      "<class 'cell'>\n"
     ]
    }
   ],
   "source": [
    "# 函数闭包产生的条件：内部函数，作为返回值返回到外部，在外部调用。\n",
    "def out_f():\n",
    "    a = 45\n",
    "    def in_f():\n",
    "        print(a)     # 只有使用了外部的变量，才会生成闭包\n",
    "        # pass\n",
    "    print('函数的闭包：', in_f.__closure__)\n",
    "    return in_f\n",
    "\n",
    "\n",
    "ff = out_f()\n",
    "ff()\n",
    "print('函数的闭包：', ff.__closure__)\n",
    "print(type(ff.__closure__))\n",
    "print(type(ff.__closure__[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 闭包的类型与帮助"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class cell in module builtins:\n",
      "\n",
      "class cell(object)\n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __eq__(self, value, /)\n",
      " |      Return self==value.\n",
      " |  \n",
      " |  __ge__(self, value, /)\n",
      " |      Return self>=value.\n",
      " |  \n",
      " |  __getattribute__(self, name, /)\n",
      " |      Return getattr(self, name).\n",
      " |  \n",
      " |  __gt__(self, value, /)\n",
      " |      Return self>value.\n",
      " |  \n",
      " |  __le__(self, value, /)\n",
      " |      Return self<=value.\n",
      " |  \n",
      " |  __lt__(self, value, /)\n",
      " |      Return self<value.\n",
      " |  \n",
      " |  __ne__(self, value, /)\n",
      " |      Return self!=value.\n",
      " |  \n",
      " |  __repr__(self, /)\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  cell_contents\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes defined here:\n",
      " |  \n",
      " |  __hash__ = None\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 获取cell的帮助（这个类不能直接查看帮助，只能依托具体的对象查看帮助）\n",
    "help(type(ff.__closure__[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. 闭包的内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "45\n"
     ]
    }
   ],
   "source": [
    "print(ff.__closure__[0].cell_contents)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 函数的属性\n",
    "\n",
    "1. 在函数中定义不了属性，但可以通过函数对象定义属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'f_a': 100, 'f_b': 600}\n"
     ]
    }
   ],
   "source": [
    "def my_func(a: int, b: int=3, *, c: int = 40, d: int) -> int:\n",
    "    \"\"\"\n",
    "    注释文档\n",
    "    \"\"\"\n",
    "    re = 30\n",
    "    return a + b\n",
    "\n",
    "my_func.f_a = 100\n",
    "my_func.f_b = 600\n",
    "print(my_func.__dict__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. 说明：\n",
    "    - 一般函数属性没有什么用处，一般用于非常专用（专业的语法解析器什么的应用），或者仅仅是传递一个数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数装饰器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器的使用背景\n",
    "\n",
    "- 装饰器语法提出的背景是回调（从语法上就是使用函数作为参数传递调用），Python提供了一种更加简洁的回调语法：装饰器（一种软件设计模式的称呼：装饰器模式）。\n",
    "    \n",
    "- 下面是一个回调的经典例子（这种耦合设计，与Qt的信号与槽非常类似）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "信息日志: 日志记录\n",
      "业务处理\n",
      "信息日志: 日志记录\n",
      "网络日志: 日志记录\n",
      "业务处理\n",
      "网络日志: 日志记录\n"
     ]
    }
   ],
   "source": [
    "def txt_log(info):\n",
    "    print('信息日志:',info)\n",
    "\n",
    "\n",
    "def net_log(info):\n",
    "    print('网络日志:',info)\n",
    "\n",
    "def biz(lg):\n",
    "    lg('日志记录')\n",
    "    print('业务处理')\n",
    "    lg('日志记录')\n",
    "    \n",
    "\n",
    "biz(txt_log)\n",
    "biz(net_log)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器的内置编程模式\n",
    "\n",
    "- 上面是回调来自传统的语法调用，这个编程模式增加了函数之间的耦合程度（因为参数属于函数的一部分），尽管Python宽松的参数类型检查，降低了这种耦合，不像其他语言通过接口等诸多语法来降低这种耦合。但是Python还是提供了一种语法来提供更加便捷的调用方式。\n",
    "\n",
    "\n",
    "- 装饰器就是一种编程模式的语法级实现（给已知函数添加新的功能）。\n",
    "    - 利用python的两个语法：\n",
    "        - 函数参数可以传递函数；\n",
    "        - 函数可以返回函数；\n",
    "    - 确定被装饰的函数，编写一个装饰函数；装饰函数的逻辑如下：\n",
    "        - 装饰函数提供一个参数，用来传递被装饰的函数；\n",
    "        - 实现一个内部函数，内部函数，在内部函数中调用被装饰的函数，再调用被装饰的函数的实现中，可以添加额外的功能。\n",
    "        - 把内部函数作为装饰函数的返回值。\n",
    "        - 当调用返回的函数的时候，这个函数已经对传递的函数提供了额外的功能。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "额外增加的功能！\n",
      "被装饰功能实现\n",
      "其他额外功能增加\n"
     ]
    }
   ],
   "source": [
    "# 1. 被装饰的函数\n",
    "def   被装饰者():\n",
    "    print('被装饰功能实现')\n",
    "    \n",
    "    \n",
    "# 2. 装饰函数：用来对被装饰者增加功能（就是装饰）\n",
    "def 装饰器(被装饰者参数):\n",
    "    # 3. 装饰实现：使用内部函数完整多被装饰者的装饰\n",
    "    def 装饰实现():\n",
    "        print('额外增加的功能！')\n",
    "        被装饰者参数()      # 调用被装饰者\n",
    "        print('其他额外功能增加')\n",
    "        \n",
    "    return 装饰实现    # 返回被装饰后的函数\n",
    "\n",
    "\n",
    "# 4. 被装饰后的函数：调用装饰器得到被装饰后的函数\n",
    "被装饰以后的函数 = 装饰器(被装饰者)\n",
    "\n",
    "# 5. 被装饰函数调用：调用返回的函数，得到被装饰的功能\n",
    "被装饰以后的函数()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器语法\n",
    "\n",
    "- 装饰器语法\n",
    "    - 装饰器语法自动实现装饰过程。\n",
    "    - 被装饰装饰过的函数就不是原来的函数了，是增加了功能的新的函数。 \n",
    "\n",
    "```python\n",
    "    @ 装饰器\n",
    "    def   被装饰函数:\n",
    "        函数实现\n",
    "        ...\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "额外增加的功能！\n",
      "被装饰功能实现\n",
      "其他额外功能增加\n"
     ]
    }
   ],
   "source": [
    "# 1. 装饰器\n",
    "def 装饰器_函数(被装饰者传递):\n",
    "    # 使用内部函数完整多被装饰者的装饰\n",
    "    def 装饰内部实现():\n",
    "        print('额外增加的功能！')\n",
    "        被装饰者传递()      # 调用被装饰者\n",
    "        print('其他额外功能增加')\n",
    "        \n",
    "    return 装饰内部实现    # 返回被装饰后的函数\n",
    "\n",
    "\n",
    "# 2 使用装饰器语法使用装饰器\n",
    "@装饰器_函数\n",
    "def   被装饰者_函数():\n",
    "    print('被装饰功能实现')\n",
    "\n",
    "    \n",
    "# 被装饰者调用\n",
    "被装饰者_函数()\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 被装饰者的参数\n",
    "\n",
    "- 明白了装饰器的原理与机制，怎么实现装饰器传递参数就容易理解，遵循调用过程传递参数。\n",
    "- 下面使用一个参数来举例说明( 其他方式的参数以此类推 )： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "额外增加的功能！\n",
      "被装饰功能实现 20\n",
      "其他额外功能增加\n"
     ]
    }
   ],
   "source": [
    "# 1. 装饰器\n",
    "def 装饰器_函数(被装饰者传递):\n",
    "    # 使用内部函数完整多被装饰者的装饰\n",
    "    def 装饰内部实现(参数):\n",
    "        print('额外增加的功能！')\n",
    "        被装饰者传递(参数)      # 调用被装饰者\n",
    "        print('其他额外功能增加')\n",
    "        \n",
    "    return 装饰内部实现    # 返回被装饰后的函数\n",
    "\n",
    "\n",
    "# 2 使用装饰器语法使用装饰器\n",
    "@装饰器_函数\n",
    "def   被装饰者_函数(参数1):\n",
    "    print('被装饰功能实现', 参数1)\n",
    "\n",
    "    \n",
    "# 被装饰者调用\n",
    "被装饰者_函数(20)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 装饰器的参数\n",
    "\n",
    "- 既然装饰器作为函数，也应该存在参数；\n",
    "- 装饰器的参数实现，采用的还是装饰器的思维，在原来的装饰器上面再装饰一层函数。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "装饰器参数: this is a 装饰器参数\n",
      "额外增加的功能！\n",
      "被装饰功能实现 20\n",
      "其他额外功能增加\n"
     ]
    }
   ],
   "source": [
    "# 1. 装饰器\n",
    "def 装饰器参数(装饰器参数):                # 装饰器参数传递\n",
    "    def 装饰器_函数(被装饰者传递):                # 装饰器函数，负责传递被装饰的函数\n",
    "        # 使用内部函数完整多被装饰者的装饰\n",
    "        def 装饰内部实现(参数):                       # 装饰实现函数，负责传递被装饰函数的参数\n",
    "            print('装饰器参数:',装饰器参数)\n",
    "            print('额外增加的功能！')\n",
    "            被装饰者传递(参数)      # 调用被装饰者\n",
    "            print('其他额外功能增加')\n",
    "\n",
    "        return 装饰内部实现    # 返回被装饰后的函数\n",
    "    return 装饰器_函数\n",
    "\n",
    "\n",
    "# 2 使用装饰器语法使用装饰器\n",
    "@装饰器参数('this is a 装饰器参数')\n",
    "def   被装饰者_函数(参数1):\n",
    "    print('被装饰功能实现', 参数1)\n",
    "\n",
    "    \n",
    "# 被装饰者调用\n",
    "被装饰者_函数(20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 多重装饰\n",
    "\n",
    "- 一般一个装饰器，肯定可以装饰多个函数，在Python语法中，一个函数也可以被多个装饰器装饰。\n",
    "    - 多个装饰器装饰本质是嵌套装饰\n",
    "    \n",
    "- 语法：\n",
    "    - 每个装饰器单独一个语句，修饰最近的函数，包括装饰器也是函数，也可以被装饰。\n",
    "\n",
    "```python\n",
    "\n",
    "    @ 装饰器1\n",
    "    @ 装饰器2\n",
    "    def 被装饰函数(参数):\n",
    "        pass\n",
    "\n",
    "    ```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "装饰器参数： 666\n",
      "开始装饰\n",
      "装饰器参数： 999\n",
      "开始装饰\n",
      "数据处理888\n",
      "装饰结束\n",
      "装饰结束\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'被装饰函数返回被装饰函数返回111'"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def log_decorator(param_log):\n",
    "    def log_wrapper(func):\n",
    "        def decorator_impl(param_func):\n",
    "            print('装饰器参数：', param_log)\n",
    "            print('开始装饰')\n",
    "            r = func(param_func)   # 被装饰函数调用(被装饰函数参数)\n",
    "            print('装饰结束')\n",
    "            return F'被装饰函数返回{r}'   # 装饰器函数的返回值\n",
    "        \n",
    "        return  decorator_impl\n",
    "    \n",
    "    return log_wrapper\n",
    "\n",
    "\n",
    "def net_decorator(param_log):\n",
    "    def net_wrapper(func):\n",
    "        def decorator_impl(param_func):\n",
    "            print('装饰器参数：', param_log)\n",
    "            print('开始装饰')\n",
    "            r = func(param_func)   # 被装饰函数调用(被装饰函数参数)\n",
    "            print('装饰结束')\n",
    "            return F'被装饰函数返回{r}'   # 装饰器函数的返回值\n",
    "        \n",
    "        return  decorator_impl\n",
    "    \n",
    "    return net_wrapper\n",
    "\n",
    "@ net_decorator(666) \n",
    "\n",
    "@ log_decorator(999)\n",
    "def biz_db(p):\n",
    "    print(F'数据处理{p}')\n",
    "    return 111\n",
    "    \n",
    "biz_db(888)\n",
    "\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## lambda表达式\n",
    "\n",
    "- lambda表达式（$\\lambda$表达式）：本质是解决函数的字面值的问题，因为通常的数据有两种形态：\n",
    "    - 字面值（也称匿名变量），比如：整数20\n",
    "    - 变量，比如：a = 20\n",
    "    \n",
    "- 函数因为其特殊性，在表示的时候，只能使用变量表示，比如函数作为参数只能传函数名，不能传函数代码。\n",
    "    - 为了能传递函数，Python语言引入了lambda表达式。\n",
    "    - lambda表达式严格意义上讲是一个自定义的运算表达式,但最终返回的实际上是一个函数对象（所以也称匿名函数）。\n",
    "    \n",
    "- lambda表达式语法：\n",
    "\n",
    "\n",
    "```python\n",
    "    lambda 参数列表: 表达式\n",
    "```\n",
    "\n",
    "- 等价于：\n",
    "```python\n",
    "    def <lambda>( 参数列表): \n",
    "        return 表达式\n",
    "```\n",
    "\n",
    "- lambda表达式没有提供参数与返回值的类型说明。\n",
    "- lambda本质是函数，使用方式与函数一样，只是比函数方便多了，可以在传函数参数的时候，直接使用lambda表达式，代码会非常简洁。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "la = lambda  x, y: x+y\n",
    "\n",
    "print(la(45, 55))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "# 定义完毕直接调用\n",
    "r = (lambda  x, y: x+y)(45,55)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'function'>\n"
     ]
    }
   ],
   "source": [
    "# 类型\n",
    "print(type( lambda  x, y: x+y ))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## main函数\n",
    "\n",
    "- 当我们写第一行语句的时候，实际代码也是通过函数运行的，这个函数就是main函数;\n",
    "- 当模块作为import，代码的__name__是模块名；只有当作为初始执行，实际是调用main来执行，__name__返回的是__main__ 。\n",
    "    - 不管使用`python  文件名`还是 `python  -m  模块名` 执行，初始执行都从__main__模块开始执行。\n",
    "\n",
    "- 判定__name__是否等于__main__可以判定一个模块是引入，还是执行开始执行的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "__main__\n"
     ]
    }
   ],
   "source": [
    "print(__name__) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Python内置标准函数\n",
    "\n",
    "- python提供了很多内置函数，前面已经调用过一些，还有一些函数位：\n",
    "\n",
    "\n",
    " &emsp; | &emsp; |  &emsp; |  &emsp; | &emsp;\n",
    "  -|-|-|-|-\n",
    "abs()\t|dict()\t|help()\t|min()\t|**setattr**()\n",
    "all()\t|dir()\t|hex()\t|next()\t|slice()\n",
    "any()\t|divmod()\t|id()\t|object()\t|**sorted**()\n",
    "ascii()\t|**enumerate**()\t|input()\t|oct()\t|**staticmethod**()\n",
    "bin()\t|**eval**()\t|int()\t|**open**()\t|str()\n",
    "bool()\t|**exec**()\t|isinstance()\t|ord()\t|sum()\n",
    "bytearray()\t|**filter**()\t|**issubclass**()\t|pow()\t|super()\n",
    "bytes()\t|float()\t|iter()\t|print()\t|tuple()\n",
    "**callable**()\t|**format**()\t|**len**()\t| **property**()\t|type()\n",
    "chr()\t|frozenset()\t|list()\t| range()\t|  **vars**()\n",
    "classmethod()\t|**getattr()**\t|**locals**()\t| **repr**()\t|**zip**()\n",
    "compile()\t|**globals**()\t|**map**()\t|**reversed**()\t|\\_\\_import\\_\\_()\n",
    "complex()\t|**hasattr**()\t|max()\t|round()\t \n",
    "**delattr**()\t|**hash**()\t|**memoryview**()\t|set()\t|  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. sorted函数\n",
    "    - 序列数据排序\n",
    "    \n",
    "```python\n",
    "    sorted(iterable, /, *, key=None, reverse=False)\n",
    "        Return a new list containing all items from the iterable in ascending order.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5]\n",
      "['Tom', 'Jack', 'Rose']\n"
     ]
    }
   ],
   "source": [
    "lt = [1, 5, 3, 4, 2]\n",
    "sorted_lt = sorted(lt)\n",
    "print(sorted_lt)\n",
    "\n",
    "# key是一个回调函数，用来处理复杂数据项的处理\n",
    "dt = {\n",
    "    'Jack': 89,\n",
    "    'Rose': 78,\n",
    "    'Tom': 99\n",
    "}\n",
    "# 使用ley处理复杂数据\n",
    "sorted_dt = sorted(dt, key= lambda x : dt[x], reverse=True)\n",
    "print(sorted_dt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. reversed\n",
    "    - 对序列数据做逆操作\n",
    "\n",
    "```python\n",
    "    class reversed(object)\n",
    "     |  reversed(sequence) -> reverse iterator over values of the sequence\n",
    "     |  \n",
    "     |  Return a reverse iterator\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<list_reverseiterator object at 0x103e40518>\n",
      "[2, 4, 3, 5, 1]\n"
     ]
    }
   ],
   "source": [
    "lt = [1, 5, 3, 4, 2]\n",
    "reversed_lt = reversed(lt)\n",
    "\n",
    "# 返回逆序可迭代对象\n",
    "print(reversed_lt)      \n",
    "print(list(reversed_lt))        # 返回的不是列表，是迭代器，可以直接转换为list类型使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. filter函数\n",
    "    - 过滤数据\n",
    "    \n",
    "```python\n",
    "    class filter(object)\n",
    "     |  filter(function or None, iterable) --> filter object\n",
    "     |  \n",
    "     |  Return an iterator yielding those items of iterable for which function(item)\n",
    "     |  is true. If function is None, return the items that are true.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 5, 3, 4, 2]\n",
      "<filter object at 0x103e60c88>\n",
      "[4, 2]\n"
     ]
    }
   ],
   "source": [
    "lt = [1, 5, 3, 4, 2]\n",
    "filter_lt = filter(None, lt)\n",
    "\n",
    "print(list(filter_lt))\n",
    "\n",
    "# 使用lambda函数，过滤奇数\n",
    "filter_lt = filter(lambda x : True if x % 2 ==0 else False, lt)\n",
    "print(filter_lt)     # filter对象也是迭代器。\n",
    "print(list(filter_lt))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "4. map函数\n",
    "    - 对数据做对应映射处理\n",
    "```python\n",
    "    class map(object)\n",
    "     |  map(func, *iterables) --> map object\n",
    "     |  \n",
    "     |  Make an iterator that computes the function using arguments from\n",
    "     |  each of the iterables.  Stops when the shortest iterable is exhausted.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 25, 9, 16, 4]\n",
      "<map object at 0x103ea5588>\n",
      "[6, 15, 6, 4, 8]\n"
     ]
    }
   ],
   "source": [
    "# 技术每个数的平方，使用生成器表达式也可以\n",
    "lt1 = [1, 5, 3, 4, 2]\n",
    "# 使用ley处理复杂数据\n",
    "map_lt = map(lambda x : x**2, lt1)\n",
    "print(list(map_lt))\n",
    "\n",
    "\n",
    "lt2 = [6, 3, 2, 1, 4]\n",
    "map_lt = map(lambda x, y : x * y, lt1,lt2)    # 如果有单个列表，则处理函数就有三个参数\n",
    "\n",
    "print(map_lt)    # map对象\n",
    "print(list(map_lt))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "5. zip函数\n",
    "    - 合并数据位元组。\n",
    "   \n",
    "\n",
    "```python\n",
    "    class zip(object)\n",
    "     |  zip(iter1 [,iter2 [...]]) --> zip object\n",
    "     |  \n",
    "     |  Return a zip object whose .__next__() method returns a tuple where\n",
    "     |  the i-th element comes from the i-th iterable argument.  The .__next__()\n",
    "     |  method continues until the shortest iterable in the argument sequence\n",
    "     |  is exhausted and then it raises StopIteration.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<zip object at 0x103e729c8>\n",
      "[(1, 6), (5, 3), (3, 2), (4, 1), (2, 4)]\n"
     ]
    }
   ],
   "source": [
    "lt1 = [1, 5, 3, 4, 2, 88]\n",
    "lt2 = [6, 3, 2, 1, 4]\n",
    "# 返回长度，取最短的长度\n",
    "zip_lt = zip(lt1, lt2)\n",
    "print(zip_lt)     # zip对象\n",
    "print(list(zip_lt))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. format函数\n",
    "    - 格式化字符串\n",
    "   \n",
    "\n",
    "```python\n",
    "    format(value, format_spec='', /)\n",
    "        Return value.__format__(format_spec)\n",
    "\n",
    "        format_spec defaults to the empty string.\n",
    "        See the Format Specification Mini-Language section of help('FORMATTING') for\n",
    "        details.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 格式化规范如下：\n",
    "\n",
    "```c++\n",
    "\n",
    "    format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]\n",
    "    fill            ::=  <any character>\n",
    "    align           ::=  \"<\" | \">\" | \"=\" | \"^\"\n",
    "    sign            ::=  \"+\" | \"-\" | \" \"\n",
    "    width           ::=  digit+\n",
    "    grouping_option ::=  \"_\" | \",\"\n",
    "    precision       ::=  digit+\n",
    "    type            ::=  \"b\" | \"c\" | \"d\" | \"e\" | \"E\" | \"f\" | \"F\" | \"g\" | \"G\" | \"n\" | \"o\" | \"s\" | \"x\" | \"X\" | \"%\"\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+2.00e+01\n"
     ]
    }
   ],
   "source": [
    "a = 20\n",
    "\n",
    "f_a = format(a, '>+5.2e')\n",
    "print(f_a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "7. open函数\n",
    "    - 打开一个文件位文件对象流。\n",
    "   \n",
    "\n",
    "```python\n",
    "    open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)\n",
    "        Open file and return a stream.  Raise IOError upon failure.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "import os\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "def list_dir(d, depth):\n",
      "\n",
      "    fd = os.path.basename(d)\n",
      "\n",
      "    print('  ' * depth, fd, sep='|-')\n",
      "\n",
      "    v = []\n",
      "\n",
      "    if os.path.isdir(d):\n",
      "\n",
      "        files = os.listdir(d)\n",
      "\n",
      "        for file in files:\n",
      "\n",
      "            file_path = os.path.join(d, file)\n",
      "\n",
      "            r = list_dir(file_path, depth + 1)\n",
      "\n",
      "            v.append(r)\n",
      "\n",
      "    return {d: v}\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "re = list_dir('.', 1)\n",
      "\n",
      "print(re)\n",
      "\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 在python中打开的文件也是一个可迭代的对象\n",
    "fd = open('recurit.py')\n",
    "for line in fd:\n",
    "    print(line)\n",
    "fd.close()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['import os\\n', '\\n', '\\n', 'def list_dir(d, depth):\\n', '    fd = os.path.basename(d)\\n', \"    print('  ' * depth, fd, sep='|-')\\n\", '    v = []\\n', '    if os.path.isdir(d):\\n', '        files = os.listdir(d)\\n', '        for file in files:\\n', '            file_path = os.path.join(d, file)\\n', '            r = list_dir(file_path, depth + 1)\\n', '            v.append(r)\\n', '    return {d: v}\\n', '\\n', '\\n', \"re = list_dir('.', 1)\\n\", 'print(re)\\n', '\\n']\n"
     ]
    }
   ],
   "source": [
    "# 在python中打开的文件也是一个可迭代的对象\n",
    "fd = open('recurit.py')\n",
    "\n",
    "lines = list(fd)\n",
    "print(lines)\n",
    "\n",
    "fd.close()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "8. vars，globals与locals函数\n",
    "    - 返回当前作用域的全局变量与局部变量\n",
    "    - 如果vars不指定参数，vars与locals是一样的效果。\n",
    "    - 如果使用参数，等于调用指定对象的__dict__\n",
    "   \n",
    "\n",
    "```python\n",
    "    vars(...)\n",
    "        vars([object]) -> dictionary\n",
    "\n",
    "        Without arguments, equivalent to locals().\n",
    "        With an argument, equivalent to object.__dict__.\n",
    "```\n",
    "\n",
    "\n",
    "```python\n",
    "    globals()\n",
    "        Return the dictionary containing the current scope's global variables.\n",
    "```\n",
    "\n",
    "\n",
    "```python\n",
    "    locals()\n",
    "        Return a dictionary containing the current scope's local variables.\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'l_a': 89}\n",
      "{'l_a': 89}\n",
      "{'a': 20}\n"
     ]
    }
   ],
   "source": [
    "g = globals()\n",
    "l = locals()\n",
    "# print(g)\n",
    "# print(l)\n",
    "\n",
    "def ff():\n",
    "    l_a = 89\n",
    "    print(locals())\n",
    "    print(vars())\n",
    "\n",
    "ff()\n",
    "\n",
    "ff.a=20    # 给函数增加一个属性\n",
    "v = vars(ff)\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "9. eval与exec函数\n",
    "    - 计算或者执行Python语句与表达式。\n",
    "   \n",
    "\n",
    "```python\n",
    "    eval(source, globals=None, locals=None, /)\n",
    "        Evaluate the given source in the context of globals and locals.\n",
    "```\n",
    "\n",
    "```python\n",
    "    exec(source, globals=None, locals=None, /)\n",
    "        Execute the given source in the context of globals and locals.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "heloo\n",
      "(25.0, 20, None)\n"
     ]
    }
   ],
   "source": [
    "epr = ' 20 + (40-10) / 6, 20, print(\"heloo\")'\n",
    "r = eval(epr)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "heloo\n",
      "None\n",
      "0.49999999999999994\n"
     ]
    }
   ],
   "source": [
    "epr = '20 + (40-10) / 6, 20, print(\"heloo\"), 30'\n",
    "r =exec(epr)    # 只是执行，不返回值\n",
    "print(r)\n",
    "\n",
    "epr = 'import math; r = math.sin(math.pi/6); print(r)'\n",
    "exec(epr)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [Root]",
   "language": "python",
   "name": "Python [Root]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "256px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
